package proxy

import (
	system "awesomeProxy/system/common"
	"awesomeProxy/system/helper"
	"awesomeProxy/system/tcpClient"
	"encoding/json"
	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"
	"time"
)

type ProxyClient struct {
	ProxyHost      string
	ProxyPort      int
	ConnectionInit sync.Map
	TargetHost     string
	TargetPort     int
	UniqueId       string
}

func (proxyClient *ProxyClient) CreateNewWorkConn() {
	connectionRelation := ConnectionRelation{}
	client := tcpClient.TcpClient{}
	client.OnConnect(func(connection net.Conn) {
		SetKeepAlive(connection.(*net.TCPConn))
		connectionRelation.SourceCon = connection
		controlMsg := ControlMsg{
			UniqueId: proxyClient.UniqueId,
			Action:   ACTION_TRANSFORM,
		}
		data, err := system.JsonEncode(controlMsg)
		if err != err {
			connection.Close()
		} else {
			connection.Write([]byte(data))
		}
	})
	client.OnMessage(func(connection net.Conn, message []byte) {
		fmt.Println("接受到客户端的请求" + helper.Now())
		err := connectionRelation.SendToOtherConnection(connection, message)
		if err != nil {
			fmt.Println(err)
		}
	})
	targetConnection := tcpClient.TcpClient{}
	targetConnection.OnConnect(func(connection net.Conn) {
		connectionRelation.TargetCon = connection
	})
	targetConnection.OnMessage(func(connection net.Conn, message []byte) {
		err := connectionRelation.SendToOtherConnection(connection, message)
		if err != nil {
			fmt.Println(err)
		}
	})
	targetConnection.OnDisConnect(func(connection net.Conn) {
		if connection, err := client.TryGetConn(time.Second, 5); err == nil {
			fmt.Println("因为与服务器连接断开，主动断开与代理服务器的连接" + helper.Now())
			connection.Close()
		}
	})
	client.OnDisConnect(func(connection net.Conn) {
		fmt.Println("断开与代理服务器的连接")
	})

	fmt.Println(proxyClient.TargetHost, proxyClient.TargetPort, "======>")
	go targetConnection.Connect(proxyClient.TargetHost, proxyClient.TargetPort, true)
	go client.Connect(proxyClient.ProxyHost, proxyClient.ProxyPort, true)
}
func (proxyClient *ProxyClient) Start() {
	client := tcpClient.TcpClient{}
	client.OnConnect(func(connection net.Conn) {
		SetKeepAlive(connection.(*net.TCPConn))
		fmt.Println(helper.Format("代理客户端成功连接到服务器访问方式:"+"http://{}:{}/?unique_id={}",
			proxyClient.ProxyHost, strconv.Itoa(proxyClient.ProxyPort), proxyClient.UniqueId))
		controlMsg := ControlMsg{
			UniqueId: proxyClient.UniqueId,
			Action:   ACTION_CONTROL,
		}
		data, err := system.JsonEncode(controlMsg)
		if err != err {
			connection.Close()
		} else {
			connection.Write([]byte(data))
		}
		go func() {
			timer := time.NewTicker(time.Millisecond * 500)
			for true {
				_ = <-timer.C
				controlMsg := ControlMsg{
					UniqueId: proxyClient.UniqueId,
					Action:   ACTION_PING,
				}
				data, err := system.JsonEncode(controlMsg)
				if err != nil {
					_, err = connection.Write([]byte(data))
					if err != nil {
						connection.Close()
						break
					}
				}
			}
		}()
	})
	client.OnMessage(func(connection net.Conn, message []byte) {
		if _, ok := proxyClient.ConnectionInit.Load(connection); !ok {
			splitMessage := strings.Split(string(message), SPLITE_CHAR)
			for _, mes := range splitMessage {
				mes = strings.TrimSpace(mes)
				if mes == "" {
					continue
				}
				res := ResponseMsg{}
				err := json.Unmarshal([]byte(mes), &res)
				if err != nil {
					fmt.Println(err, "异常")
				} else {
					switch res.Action {
					case ACTION_CREATE_WORK:
						fmt.Println("成功连接到代理服务器" + connection.RemoteAddr().String())
						proxyClient.CreateNewWorkConn()
					}
				}
			}
		}
	})
	client.OnError(func(err error) {
		fmt.Println("断开连接正在尝试重新连接")
		time.Sleep(time.Second * 2)
		go proxyClient.Start()
	})
	client.OnDisConnect(func(connection net.Conn) {
		fmt.Println("断开连接正在尝试重新连接")
		time.Sleep(time.Second * 2)
		go proxyClient.Start()
	})
	client.Connect(proxyClient.ProxyHost, proxyClient.ProxyPort, false)
}
